#pragma once
#include "CpUtil.h"

namespace CppClean
{

class CToken : public CCpObject
{
public:
	enum TokenType
	{
		eTTUnknown,
		eTTSyntax,
		eTTConstant,
		eTTName,
		eTTPreprocessor,
		eTTInternal,
	};

	enum WhenceType
	{
		eWhenceStream,
		eWhenceQueue,
	};
	typedef std::deque<CCpAutoPtr<CToken> > TOKEN_LIST;

public:
	CToken(TokenType eType, LPCSTR lpszName, UINT nStart, UINT nEnd, WhenceType eWhence = eWhenceStream)
		:m_eType(eType), m_sName(lpszName), m_nStart(nStart), m_nEnd(nEnd), m_eWhence(eWhence) {}
	virtual ~CToken() {}

	virtual string GetString();
	virtual string GetName()
	{
		return m_sName;
	}

	void OutputDebug();

public:
	TokenType m_eType;
	string m_sName;
	UINT m_nStart;
	UINT m_nEnd;
	WhenceType m_eWhence;
};

class CTokenizer
{
public:
	CTokenizer(const char* pData, DWORD dwSize);
	~CTokenizer(void);

public:
	CToken* GetNextToken();

public:

private:
	bool IsStringPrefix(const char* s, int start, int end);
	int GetString(int start, int curr);
	int GetChar(int start, int curr);

	CHARSET m_aIdentifies;
	CHARSET m_aHex;
	CHARSET m_aDigits;
	CHARSET m_aDigits2;
	STRINGSET m_aStringPrefixs;

	char* m_szSource;
	DWORD m_dwEndPos;
	DWORD m_dwStart;
	DWORD m_dwCurrent;
	BOOL m_bIgnoreErrors;	//# Only ignore errors while in a #if 0 block.
	int m_nCountIfs;
};

class CKeyword
{
public:
	CKeyword();
	~CKeyword() {}

public:
	static bool IsKeyword(const char* str);
	static bool IsBuiltInType(const char* str);

private:
	STRINGSET m_aAll;
	STRINGSET m_aBuiltIn;
};

}
